<?php

/**
 * Ignus Framework
 *
 * @author Sergey Palyanov <sergey.palyanov@gmail.com>
 * @link http://code.google.com/p/ignus-php/
 * @license http://apache.org/licenses/LICENSE-2.0
 * @package Db
 * @subpackage Mongodb
 * @since 0.3
 */

namespace Ignus\Db\Mongodb;

/**
 * @package Db
 * @subpackage Mongodb
 * @since 0.5.6
 */
class MongoGroup
{
    /**
     * @var \MongoCollection
     */
    private $collection;

    /**
     * @var array
     */
    private $keys = array();

    /**
     * @var array
     */
    private $query = array();

    /**
     * @var array
     */
    private $initial;

    /**
     * @var string
     */
    private $reduce;

    /**
     * @var string|null
     */
    private $finalize = null;

    /**
     * Sort function
     * @var callback|null
     */
    private $sort = null;

    /**
     * @param \MongoDB $collection
     */
    public function __construct(\MongoCollection $collection)
    {
        $this->collection = $collection;
    }

    /**
     * Set document keys to group by
     * @param array $keys
     * @return MongoGroup
     */
    public function keys(array $keys)
    {
        $this->keys = array_fill_keys($keys, true);
        return $this;
    }

    /**
     * Specify query
     * @param array $query
     * @return MongoGroup
     */
    public function query(array $query)
    {
        $this->query = $query;
        return $this;
    }

    /**
     * Specify reduce function and initial object
     * @param array $initial Initial value
     * @param string $reduce Aggregate function
     * @return MongoGroup
     */
    public function reduce(array $initial, $reduce)
    {
        $this->initial = $initial;
        $this->reduce = $reduce;
        return $this;
    }

    /**
     * Specify finalize function
     * @param string $finalize
     * @return MongoGroup
     */
    public function finalize($finalize)
    {
        $this->finalize = $finalize;
        return $this;
    }

    /**
     * Sort function
     * @param callback $callback
     * @return void
     */
    public function sort($callback)
    {
        $this->sort = $callback;
    }

    /**
     * Executes grouping
     * @return array
     */
    public function run()
    {
        $options['condition'] = $this->query;
        if ($this->finalize != null)
            $options['finalize'] = $this->finalize;

        $result = $this->collection->group($this->keys, $this->initial, $this->reduce, $options);

        if ($this->sort != null)
            usort($result['retval'], $this->sort);

        return $result;
    }
}
